import string
import re
import random
import nltk, re, pprint
import numpy
from nltk.corpus import brown
import Recipe
from nltk.corpus import wordnet as wn
import classifier

######REPLACE WITH REGEXES####
modals = "do will should would can could".split()
desire_verbs = "love like need hate dislike".split()
action_verbs = "want to search look try make do".split()
be_verbs = "is are am feel".split()

next_words = "next", "proceed", "continue", "go on", "complete", "done", "move on" 
recipe_words = "recipe", "the recipe"

cont_responses = ["Ok, are you still following me?",
	"Are you ready to move on?",
	"Let me know when you're ready to continue.",
	"Would you like to continue to the next step?"]

class Parser(object):
	def __init__(self):
		self.nouns_list = []
		self.sentence = ""
		self.sentence_list = []
		self.tree = []
		self.rec = ""


	def parse(self):
		self.sentence_list = nltk.word_tokenize(self.sentence)
		sentence = self.sentence_list
		#self.sentence = self.sentence.lower()
		
		############ GRAMMAR ###########################################
		grammar = r"""
			S: {<NP|WH><VP>.*}
			WH:{<W.*><NP>?}
			NP:{<DT|PP\$>?<JJ>*<NN|NNS>+<CC>?<DT|PP\$>?<JJ>*<NN|NNS>+}
			   {<DT|PP\$>?<JJ>*<NN|NNS>+}
			   {<NNP>+}
			   {<VBG><NN|NNS>?}
			PNP:{<PRP>}
			VP:{<VB.*><NP>*}
			PP:{<IN><NP>?}
			AdvP:{<RB>?<JJ>+}
		"""
		############ PARSING TOOLS ####################################
		
		cp = nltk.RegexpParser(grammar)
		tags = nltk.pos_tag(sentence)
		
		###### TREE PARSING ########################################### 
		
		tree = cp.parse(tags)
		self.tree = tree
		
		############ SIMPLE WITH TAGS ###########################
		x = 0
		nouns = []
		nouns_list = []
		verbs = []
		for pos in tags:
			if pos[1]== 'NN' or pos[1]=='NNS' or pos[1]=='JJ':				
				nouns.append(pos)
				nouns_list.append(pos[0])
			if pos[1]=='VBP' or pos[1]=='VB':
				verbs.append(pos[0])
		return nouns_list
				
	#################### parsing functions ###########################
				
	def formResponse(self, recipe):
		nouns = self.parse()
		if classify (self.sentence, 'startover'):
			return(self.sentence)

		# identify wh-words and questions		
		if classify (self.sentence, 'thank'):
			return('You\'re very welcome.')

		elif classify (self.sentence, 'show'):
			return(self.showResponse(self.tree, recipe))

		#this function identifies step-by-step mode#
		elif classify (self.sentence, 'steps'):
			self.momma('I would love to walk you through it. Let\'s proceed.')
			return self.walkThrough(recipe, 0)
			
		elif self.getXP(self.tree, 'WH') != []:
			self.momma( self.whResponse(self.tree))
			self.momma('Here, I\'ll show you the directions again.')
			self.momma(recipe.pretty_print2 ('directions'))
			return('I hope that helps')
			
		# identify statements the user makes about his/herself
		# Momma will respond with a question and get their response
		elif self.getXP(self.tree, 'PNP') == ['i']:
			self.momma(self.userInfoResponse(self.tree))
			resp = raw_input(">")
			return('Oh now isn\'t that nice.')
			
		else:
			self.momma('Sorry, I\'m not sure how to help.')
			return('I can walk you through the steps again or show you the recipe you selected?')

	############ RESPONSE FUNCTIONS ###########################		
		
	def showResponse(self, Tree, recipe):
		noun = ''
		object = self.getObject(self.tree, 'VP')
		if object == []:
			object = self.getObject(self.tree, 'PP')
			if object == []:
				object = self.getNPafterVP(self.tree)
				if object == []:
					object = self.getXP(self.tree, 'NP')
					if object == []:
						self.momma('Sorry, I didn\'t get that. What would you like to see?.')
						resp = raw_input(">")
						self.usersays(resp)
						object.append(resp)
		answer = 'Ok. Here you are dear,'
		for word in object:
			if classify(word, 'show'):
				object.remove(word)
			else:
				noun += word+' '
				answer += ' ' + word
		print "\n"
		if classify(noun, 'recipe'):
			self.momma(answer+':'+recipe.pretty_print())
			print "\n"
			return ' '
		if classify(noun, 'ingredients'):
			self.momma(answer+':' + recipe.pretty_print2 ('ingredients')	)
			print "\n"
			return ' '
		elif classify(noun, 'steps'):
			self.momma(answer+':'+recipe.pretty_print2 ('directions'))
			print "\n"
			return ' '
		else:
			if object != []:
				answer = 'I\'m sorry, I have nothing to show you about'
				for word in object:
					answer += ' ' + word
				answer += '.'
			else:
				answer = 'Could you be more specific?'
			return answer

	def walkThrough(self, recipe, step_num):
		for i in range(step_num, len(recipe.directions)):
			self.momma(recipe.directions[i])
			#print random statement to proceed
			self.momma(cont_responses[random.randint(0,len(cont_responses)-1)])
			self.stepByStep(recipe, i)
			if classify(self.sentence, 'quit') or classify(self.sentence, 'no'):
				return "Thanks for cooking with me today."
		return('You did it! Well done!')
			
	def stepByStep(self, recipe, int):
		s = raw_input(">")
		self.usersays(s)
		user_response = s.lower()
		self.sentence = user_response
		if classify(user_response, 'back'):
			if int == 0:
				self.momma('We\'re already at step 1, silly!')
				self.walkThrough(recipe, int)
			else:
				self.momma('Sure, we can revisit that last step.')
				self.walkThrough(recipe, int-1)
		elif classify(user_response, 'quit'): 
			self.momma('Perhaps you\'re just not cut out for the kitchen.')
			return "exit"
		elif classify(user_response, 'yes'):
			return
		elif classify(user_response, 'no'):
			self.momma('Ok then let\'s try that again...')
			self.walkThrough(recipe, int)
		else:
			self.momma(self.formResponse(recipe))
			self.momma('Shall we continue step by step?')
			resp = raw_input(">")
			self.usersays(resp)
			r = resp.lower()
			self.sentence = r
			if classify (r, 'yes'):
				return (self.momma("Ok let's move on..."))
			elif classify(r, 'no'):
				return
				
	def whResponse(self,Tree):
		answer = ''
		wh_word = self.getXP(Tree, 'WH')
		wh = wh_word[0].lower()
		answer = 'You want to know '+wh
		default = 'Sorry, I don\'t know much about'
		#when responding with verb reflection, drop modals
		action = self.getVerb(Tree)
		#print action
		for v in action: 
			if v in be_verbs:
				answer = default
			elif not v in modals:
				answer+=' to '+v		
		if self.getObject(Tree, 'VP') != []:
			vp_object = self.getObject(Tree, 'VP')
			for node in vp_object: 
				answer+=' '+node
		if self.getXP(Tree, 'PP') != []:
			if answer == default:
				pp_object = self.getObject(Tree, 'PP')
			else:
				pp_object = self.getXP(Tree, 'PP')
			for node in pp_object: answer+=' '+node	
		if self.getXP(Tree, 'AdvP') != []:
			advp_object = self.getXP(Tree, 'AdvP')
			for node in advp_object: answer+=' '+node		
		return answer+'.'
	
	def userInfoResponse(self,Tree):
		answer = ''
		default = 'You talk about yourself an awful lot. Let\'s focus on cooking.'
		action = self.getVerb(Tree)
		for v in action: 
			#if they want or like something...
			if v in desire_verbs:
				answer += 'Oh Really? What do you '+v+' about'
				if self.getObject(Tree, 'VP') != []:
					vp_object = self.getObject(Tree, 'VP')
					for node in vp_object:
						answer+=' '+node
				elif self.getXP(Tree, 'AdvP') != []:
					advp_object = self.getXP(Tree, 'AdvP')
					for node in advp_object: answer+=' '+node
				elif self.getObject(Tree, 'PP') != []:
					pp_object = self.getObject(Tree, 'PP')
					for node in pp_object: answer+=' '+node
				else: return default
				answer +='?'
				return answer
				
			#if they want to do something... 
			if v in action_verbs:
				answer += 'Do you want to'
				if self.getXP(Tree, 'VP') != []:
					vp = self.getXP(Tree, 'VP')
					if 'want' in vp:
						vp.remove('want')
					for node in vp: 
						answer+=' '+node
				if self.getXP(Tree, 'AdvP') != []:
					advp_object = self.getXP(Tree, 'AdvP')
					for node in advp_object: answer+=' '+node
				answer += ' today?'
				return answer
				
			#if they are telling momma about themselves
			if v in be_verbs:
				answer += 'Why are you'
				if self.getXP(Tree, 'AdvP') != []:
					advp_object = self.getXP(Tree, 'AdvP')
					for node in advp_object:
						if classify(v, 'hungry'):
							answer = 'You\'re hungry!? Well let\'s get cooking!'
							return answer
						answer+=' '+node
				if self.getXP(Tree, 'PP') != []:
					pp_object = self.getXP(Tree, 'PP')
					for node in pp_object: answer+=' '+node		
				answer += '?'
				return answer
			else:
				return default
		else: 
			return default
		
	#################### TREE FUNCTIONS #############################
	def getXP(self,Tree, str):
		xp = []
		for child in Tree:
			if isinstance(child, nltk.Tree):
				if child.node == str:
					for leaf in child.leaves():
						xp.append(leaf[0])							
		return xp
		
	#############!!!!! refine this function !!!!!#########
	def getNPafterVP(self, Tree):
		xp = []
		flag = False
		for child in Tree:
			if isinstance(child, nltk.Tree):
				if child.node == 'VP':
					flag = True
			if flag == True:
				if isinstance(child, nltk.Tree):
					if child.node == 'NP':
						for leaf in child.leaves():
							xp.append(leaf[0])							
		return xp
							
	#getObject(sub_tree, obj_of_str)
	def getObject(self,Tree, str):
		xp_obj = []
		for child in Tree:
			if isinstance(child, nltk.Tree):
				if child.node == str:
					if self.getXP(child, 'NP') != []:
						xp_obj = self.getXP(child, 'NP')
		return xp_obj
		
	def getVerb(self,Tree):
		verb = []
		regex = re.compile('VB.*')
		for child in Tree:
			if isinstance(child, nltk.Tree):
				if child.node == 'VP':
					for leaf in child.leaves():
						if regex.match(leaf[1]):
							verb.append(leaf[0])
		return verb
							
	def printLeaves(self,Tree):
		for child in Tree:
			if isinstance(child, nltk.Tree):
				printLeaves(child)
			else:
				print child
				
	def momma(self,s):
		print s


def classify(s,t):
	return  classifier.classify(s,t)